package comm;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;


//------------------------ START inner class SocketHandler ---------------	
//estas threads vão ser adicionadas ao hashmap usando como key o nickname do utilizador a qual estão associadas.
//cada thread gere a sua ligação e fica à escuta de novas mensagens.

//AUXILIAR O SERVER SIDE

/**
 * This class helps handling multiple clients that tries to connect to a server by having
 * a specific socketHandler assigned to each of those clients
 */
class SocketHandler extends Thread{
	private Socket socket;
	private ServerInterface commInterface;
	private ObjectInputStream in;
	private ObjectOutputStream out;
	private Boolean connected = true;

	/**
	 * Constructor that receives the Socket and the ServerInterface instance
	 * 
	 * @param s		socket used to communicate
	 * @param comm	ServerInterface instance
	 * 
	 */
	public SocketHandler(Socket s , ServerInterface comm){
		super();

		this.socket = s;
		commInterface = comm;
		try {
			init();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("SERVER "+ this.getName()+" Handler created..!");
	}

	//Initialize Streams
	private void init() throws IOException {
		System.out.println("SERVER " + this.getName() + " streams created!");
		out=new ObjectOutputStream(socket.getOutputStream());
		in=new ObjectInputStream(socket.getInputStream());
	}

    /**
     * It sends a message created by the Client
     * 
     * @param message The message created by the Client
     */
	public void sendMenssage(ClientMessage message){
		try {	
			out.writeObject(message);
			out.reset();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void run(){
		ServerMessage inMessage;
		while(connected){
			System.out.println(this.getName()+" Starting to listen my client !");
			try {
				inMessage = (ServerMessage)in.readObject();
				if(inMessage.getType() == ServerSideMessage.Type.CLIENT_CONNECTED){
					commInterface.addHandlerToMap(inMessage.getClientNickname().toString(), this); 
					System.out.println("SERVER " + this.getName() +" New client binding! client nickname="+inMessage.getClientNickname());

					commInterface.sendClientConnected(inMessage.getClientNickname(),inMessage.getClientNickname());
					System.out.println(this.getName()+" confirmation msg sent!!");
				}else if(inMessage.getType() == ServerSideMessage.Type.CLIENT_DISCONNECTED){
					commInterface.disconnectClient(inMessage.getClientNickname());
					disconnect();
					System.out.println(this.getName()+" Removed client: "+inMessage.getClientNickname());

				}else{
					commInterface.addMessageToList(inMessage);
				}
			} catch (IOException e) {
				disconnect();
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}

		}
	}

	/**
	 * It closes the socket
	 */
	public void disconnect() {
		connected=false;

		try {
			socket.close();                 
			in.close();
			out.close();
		} catch (IOException e) {

			//e.printStackTrace();
		}

	}

}
//----------------------END	of SocketHandlet ------------------------------
